package com.gitee.cui.client.handler;

import com.gitee.cui.client.builder.HeartBeatMsgBuilder;
import com.gitee.cui.client.client.ClientSession;
import com.gitee.cui.common.common.bean.User;
import com.gitee.cui.common.common.bean.msg.ProtoMsg;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

/**
 * 心跳处理器
 * @author cuiqingqiang
 * @version 1.0
 * @date 2021/10/27 16:42
 **/
@Slf4j
@ChannelHandler.Sharable
@Service
public class HeartBeatClientHandler extends ChannelInboundHandlerAdapter {

    /**
     * 心跳时间间隔，单位秒
     */
    private static final int HEARTBEAT_INTERVAL = 50;

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        // 判断消息类型
        if (!(msg instanceof ProtoMsg.Message)) {
            super.channelRead(ctx, msg);
            return;
        }
        // 判断消息类型
        ProtoMsg.Message heartBeat = (ProtoMsg.Message) msg;
        ProtoMsg.HeadType type = heartBeat.getType();
        if (ProtoMsg.HeadType.HEART_BEAT != type) {
            super.channelRead(ctx, msg);
        } else {
            log.info("收到回写的心跳消息！");
        }
    }

    /**
     * 在handler被加入到pipeline时，开始发送心跳数据
     * @param ctx 通道处理器上下文
     * @throws Exception 异常信息
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        ClientSession session = ClientSession.getSession(ctx);
        User user = session.getUser();
        // 构建心跳信息
        HeartBeatMsgBuilder msgBuilder = new HeartBeatMsgBuilder(user, session);
        ProtoMsg.Message message = msgBuilder.buildMsg();
        heartBeat(ctx, message);
    }

    /**
     * 发送心跳信息
     * @param ctx 通道处理器上下文
     * @param message 心跳信息
     */
    private void heartBeat(ChannelHandlerContext ctx, ProtoMsg.Message message) {
        ctx.executor().schedule(() -> {
           if (ctx.channel().isActive()) {
               log.info("发送心跳消息给服务端");
               ctx.writeAndFlush(message);

               // 发送给下一次心跳
               heartBeat(ctx, message);
           }
        }, HEARTBEAT_INTERVAL, TimeUnit.SECONDS);
    }
}
